<!--
  - 重力感应初始化组件
 -->

<!-- 视图层 -->
<template>

<!-- 重力感应：卡片容器 -->
<uni-card title="重力感应">
  <!-- 通告栏 -->
  <uni-notice-bar text=
    "重力感应传感器的通用输出为alpha、beta、gamma三通道信息：
    alpha - 表示设备在XY平面旋转的角度，范围0~360°；
    beta - 表示设备在YZ平面旋转的角度，范围为-180~180°；
    gamma - 表示设备在XZ平面旋转的角度，范围-90~90°。"
  />
  <!-- 内容容器：条件渲染 -->
  <!-- 若浏览器支持重力感应，且内容有效不为error -->
  <view v-if="gravityStateRef && !gravityStateRef.error">
    <!-- 重力感应数据的表格容器 -->
    <uni-table
      :border="true" :stripe="true"
    >
      <!-- 标题行 -->
      <uni-tr>
        <uni-th align="center">
          轴向
        </uni-th>
        <uni-th align="center">
          角度
        </uni-th>
      </uni-tr>
      <!-- 内容行 -->
      <uni-tr v-for="(value, keyName) in gravityStateRef">
        <!-- 轴向 -->
        <uni-td align="center">
          {{ keyName }}
        </uni-td>
        <!-- 角度 -->
        <uni-td align="center">
          {{ value }}
        </uni-td>
      </uni-tr>
    </uni-table>
  </view>
  <!-- 条件渲染：若浏览器不支持重力感应API，即有gravityStateRef，但内容为error -->
  <view v-else-if="gravityStateRef && gravityStateRef.error">
    <text space="ensp">
      {{ "重力感应报错：" + gravityStateRef.error }}
    </text>
  </view>
  <!-- 条件渲染：若未返回gravityStateRef数据，则仍未初始化 -->
  <view v-else class="center">
    <button
      @click="permitGravity()"
      size="mini" type="primary"
    >
      获取重力感应数据
    </button>
  </view>
</uni-card>

</template>

<!-- 逻辑层 -->
<script setup>
// 导入vue的onMounted、ref方法
import { onMounted, ref } from "vue"

// 定义一个ref对象，用于保存重力感应状态
const gravityStateRef = ref(null)


/**
 * @启动方法
 * 生命周期钩子，组件加载完毕后执行
 */
onMounted(() => {
  // 初始化重力感应
  initGravity()
})


/**
 * @重力感应初始化
 * 只是判断浏览器是否支持重力感应API
 * @note 会写入gravityStateRef数据
 */
function initGravity() { try {
  // 看看重力感应是否可用
  if (!window.DeviceOrientationEvent) {
    // 直接写入报错信息
    gravityStateRef.value = {
      error: "当前浏览器不支持重力感应API"
    }
  }
} catch (error) {
  console.error("重力感应初始化时报错：", error)
  gravityStateRef.value = error
}}


/**
 * @申请重力感应
 * 3种情况：
 *   1. 浏览器不支持重力感应API
 *   2. 浏览器支持，但是读不到重力感应数据（权限不足或硬件不支持）
 *   3. 浏览器支持，且能读到重力感应数据
 *     3.1 苹果有个判断
 *     3.2 安卓没有
 * @note 会写入gravityStateRef数据
 */
function permitGravity() { try {
  // 看看有没有苹果的那个权限控制
  if (DeviceOrientationEvent.requestPermission) {
    // 若有，就请求
    window.DeviceOrientationEvent.requestPermission()
      // 链式调用
      .then((response) => {
        // 若用户同意，则执行回调
        if (response == "granted") {
          // 获取重力感应数据
          getGravity()
        // 用户不同意
        } else {
          // 若用户拒绝，则写入报错信息
          gravityStateRef.value = {
            error: "用户拒绝使用重力感应"
          }
        }
      })
  // 若没有那个权限控制，即安卓手机
  } else {
    // 获取重力感应数据
    getGravity()
  }
} catch (error) {
  console.error("申请重力感应时报错：", error)
  gravityStateRef.value = error
}}


/**
 * @获取重力感应数据
 * 直接用监听方法
 * @note 会写入gravityStateRef数据
 */
function getGravity() { try {
  // 注册重力感应数据监听事件，回调为ref对象赋值
  window.addEventListener("deviceorientation", (event) => {
    // 选择性赋值
    gravityStateRef.value = {
      alpha: (event.alpha) ? (event.alpha.toFixed(2)) : ("权限不足或硬件不支持"),
      beta: (event.beta) ? (event.beta.toFixed(2)) : ("权限不足或硬件不支持"),
      gamma: (event.gamma) ? (event.gamma.toFixed(2)) : ("权限不足或硬件不支持"),
    }
  })
} catch (error) {
  console.error("获取重力感应时报错：", error)
  gravityStateRef.value = error
}}

</script>
